1. /* slflldiv.cpp by K.Tsuru */
  2. // function ID = 216, 217 DRADIX, BRADIX
  3. /************************************************************
  4. SLong and SInteger class
  5. It provides a quotient m/n and a remainder m%n.
  6. Depending on the value of "pfLLDiv" the used method is Knuth
  7. or Newton.
  8. *************************************************************/
  9. #ifndef SN_H
  10. #include "sn.h"
  11. #endif
  12. // static objects of SLong class
  13. int SLong::llDivMode = SLong::reset;
  14. static const char* const func = "LLDiv";
  15. // m = n*q + r, verifying function
  16. static void DivVerify(const SLong& m, const SLong& n, const Ldiv_t& r){
  17. const char* const divfunc = (SLong::LLDivMode() == m.Knuth) ? "KnuthLLDiv" : "NewtonLLDiv";
  18. SLong t;
  19. int c = LLCompare(n, r.rem), err; //Must be c > 0 (|n| > |r.rem|).
  20. if( c <= 0 ) err = 1; // r < n ?
  21. else {
  22. SLong t;
  23. t = m - r.quot*n - r.rem; //t must be equal to zero.
  24. err = t.Sign(216);
  25. }
  26. if(err) SNManager::SetError(m.VERIFY, divfunc, 216);
  27. }
  28. //m/n, The number of figures of n is two or under.
  29. static int DivByShort(const SLong& m, const SLong& n, Ldiv_t& r){
  30. ulong d = n.Low2(); //d=n(1)*radix+n(0)
  31. if( d <= m.SlOpMaxValue() ){ //multi-precision integer/short integer
  32. long rem = 0;
  33. // r.quot = m/|n|
  34. if(d > 1uL) r.quot = LsDiv( m, d, &rem);//r.quot has tha same type as m.
  35. else r.quot = m; // |n| = 1, rem = 0;
  36. if(n.Sign() < 0) r.quot.ChangeSign(); // quot != 0, d>0, n<0
  37. r.rem.SetLong(rem); //The sign of "r.rem" is the same as that of "m",
  38. //which is considered in LsDiv() for "rem".
  39. return 1;
  40. }
  41. return 0;
  42. }
  43. Ldiv_t LLDiv(const SLong& m, const SLong& n, bool needRem){
  44. //If "verify" is ON it calcutates the remainder.
  45. if(SNManager::Verify() == ON) needRem = true;
  46. if( !n.Sign() ) m.SetError(m.DIVIDED_BY_ZERO, func, 216); // n=0
  47. int c = LLCompare(m, n); //comparing the largeness
  48. int sgn = m.Sign(216)*n.Sign(216); //the sign of quotient
  49. Ldiv_t result;
  50. result.quot.SetType(m.Type()); result.rem.SetType(m.Type());
  51. // |n| > 0
  52. if(c < 0){ // 0=< |m| < |n| quotient=0, remainder=m
  53. result.quot.SetZero(); result.rem = m;
  54. } else if(c == 0){ // |m| = |n| (!= 0)
  55. result.quot = sgn; result.rem.SetZero();
  56. }
  57. if(c <= 0) return result;
  58. // |m| > |n|
  59. if( (n.aHead > 0) && ( m.Type() != n.Type() ) ){
  60. m.SetError(m.RADIX_ERR, func, 216);
  61. }
  62. // n has two or under figures including the case |n| = 1.
  63. if( (n.Head() <= 1u) && DivByShort(m, n, result) ) return result;
  64. //The registration of default division function.
  65. // if(m.pfLLDiv == NULL) m.UsesKnuthLLDiv();
  66. //Check n = abcd efgh ... 0000 0000 or not.
  67. if(n.Tail() >= 4u){ //It divides m and n by the power of radix.
  68. //The quotient of 1234567/12000 can be obtained by 1234/12 = 102
  69. //and its remainder 1234567-102*12000=10567.
  70. SLong mc(m), nc(n);
  71. int divRdxPow = (int)n.Tail();
  72. //divide by R^divRdxPow
  73. mc.MultPowRdx(-divRdxPow); nc.MultPowRdx(-divRdxPow);
  74. //recursive call
  75. //maybe "nc < SlOpMaxValue()"
  76. result = LLDiv(mc, nc, 0);
  77. if(!needRem) return result;
  78. //remainder r=m-n*q
  79. result.rem = m - result.quot*n;
  80. if(mc.Verify()) DivVerify(m, n, result);
  81. return result;
  82. }
  83. SLong M(Labs(m)), N(Labs(n)); // M = |m|, N = |n|
  84. /*
  85. It returns the result.
  86. About the relations between quotient and remainder.
  87. m=n*q+r
  88. If the quotient is defined by the integral division q=m/n, when m<0 and n>0,
  89. q<0 and r<0.
  90. [Example]
  91. When m=-5 and n = 4, q = -5/4=-1 and r = -1.
  92. -5 = 4*(-1)+ (-1)
  93. Then the remainder has the same sign as that of m.
  94. q = 5/(-2) = -2
  95. r = 5 - (-2)*(-2) = 1 > 0
  96. 5 = (-2)*(-2) + 1
  97. */
  98. // cout << M.llDivMode << "in LLDiv" << endl;
  99. if(M.llDivMode & M.SetByUser) {
  100. result = (M.llDivMode & M.Newton) ? M.NewtonLLDiv(M, N, needRem) : M.KnuthLLDiv(M, N, needRem);
  101. } else {
  102. M.llDivMode = M.NewtonLLDivIsFaster(M, N) ? M.Newton : M.Knuth;
  103. result = (M.llDivMode == M.Newton) ? M.NewtonLLDiv(M, N, needRem) : M.KnuthLLDiv(M, N, needRem);
  104. }
  105. // cout << M.llDivMode << "in LLDiv" << endl;
  106. if(sgn < 0) result.quot.SetSign(-1); // result.quot = -result.quot
  107. if(m.Sign() < 0) result.rem.ChangeSign(216);//It allows the case that rem==0.-0=0
  108. // result.rem = -result.rem
  109. // check m = q*n + r
  110. if(M.Verify()) DivVerify(m, n, result);
  111. return result;
  112. }
  113. // 217
  114. SLong LLDiv(const SLong& m, const SLong& n) {
  115. Ldiv_t r = LLDiv(m, n, 0);
  116. return r.quot;
  117. }

slflldiv.cpp : last modifiled at 2016/07/28 16:09:14(4,408 bytes)
created at 2017/10/07 10:26:50
The creation time of this html file is 2017/11/09 14:52:03 (Thu Nov 09 14:52:03 2017).